#ifndef SANITIZER_UTILS_H
#define SANITIZER_UTILS_H
#include "asan_internal_defs.h"
#include "pthread.h"
#include "unistd.h"


namespace __sanitizer {

extern "C" {
unsigned char _BitScanForward(unsigned long *index, unsigned long mask);
unsigned char _BitScanReverse(unsigned long *index, unsigned long mask);
}

inline uptr MostSignificantSetBitIndex(uptr x) {
  unsigned long up;
  // On Arm, it is __buildin_clz
  up = SANITIZER_WORDSIZE - 1 - __builtin_clzl(x);
  // up = SANITIZER_WORDSIZE - 1 - __builtin_clz(x);
  // _BitScanReverse(&up, x);
  return up;
}

inline uptr LeastSignificantSetBitIndex(uptr x) {
  unsigned long up;
  up = __builtin_ctzl(x);
  // _BitScanForward(&up, x);
  return up;
}

inline constexpr bool IsPowerOfTwo(uptr x) {
  return (x & (x - 1)) == 0;
}


inline uptr RoundUpToPowerOfTwo(uptr size) {
  if (IsPowerOfTwo(size)) return size;

  uptr up = MostSignificantSetBitIndex(size);
  return 1ULL << (up + 1);
}

inline constexpr uptr RoundUpTo(uptr size, uptr boundary) {
  return (size + boundary - 1) & ~(boundary - 1);
}

inline constexpr uptr RoundDownTo(uptr x, uptr boundary) {
  return x & ~(boundary - 1);
}

inline constexpr bool IsAligned(uptr a, uptr alignment) {
  return (a & (alignment - 1)) == 0;
}

inline uptr Log2(uptr x) {
  return LeastSignificantSetBitIndex(x);
}

// Don't use std::min, std::max or std::swap, to minimize dependency
// on libstdc++.
template <class T>
constexpr T Min(T a, T b) {
  return a < b ? a : b;
}
template <class T>
constexpr T Max(T a, T b) {
  return a > b ? a : b;
}
template <class T>
constexpr T Abs(T a) {
  return a < 0 ? -a : a;
}
template<class T> void Swap(T& a, T& b) {
  T tmp = a;
  a = b;
  b = tmp;
}

// Char handling
inline bool IsSpace(int c) {
  return (c == ' ') || (c == '\n') || (c == '\t') ||
         (c == '\f') || (c == '\r') || (c == '\v');
}
inline bool IsDigit(int c) {
  return (c >= '0') && (c <= '9');
}
inline int ToLower(int c) {
  return (c >= 'A' && c <= 'Z') ? (c + 'a' - 'A') : c;
}



} // namespace __sanitizer



#endif // SANITIZER_UTILS_H